package cn.dansj.common.mail.utils;

import cn.dansj.common.utils.transfer.Verification;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.LinkedHashMap;
import java.util.Map;

public class MailSendException extends MailException {
    private final transient Map<Object, Exception> failedMessages;

    private final Exception[] messageExceptions;

    public MailSendException(String msg) {
        this(msg, null);
    }

    public MailSendException(String msg, Throwable cause) {
        super(msg, cause);
        this.failedMessages = new LinkedHashMap<>();
        this.messageExceptions = null;
    }

    public MailSendException(String msg, Throwable cause, Map<Object, Exception> failedMessages) {
        super(msg, cause);
        this.failedMessages = new LinkedHashMap<>(failedMessages);
        this.messageExceptions = failedMessages.values().toArray(new Exception[0]);
    }

    public MailSendException(Map<Object, Exception> failedMessages) {
        this(null, null, failedMessages);
    }

    public final Map<Object, Exception> getFailedMessages() {
        return this.failedMessages;
    }

    public final Exception[] getMessageExceptions() {
        return (this.messageExceptions != null ? this.messageExceptions : new Exception[0]);
    }


    @Override
    public String getMessage() {
        if (Verification.checkNull(this.messageExceptions)) {
            return super.getMessage();
        } else {
            StringBuilder sb = new StringBuilder();
            String baseMessage = super.getMessage();
            if (baseMessage != null) {
                sb.append(baseMessage).append(". ");
            }
            sb.append("Failed messages: ");
            for (int i = 0; i < this.messageExceptions.length; i++) {
                Exception subEx = this.messageExceptions[i];
                sb.append(subEx.toString());
                if (i < this.messageExceptions.length - 1) {
                    sb.append("; ");
                }
            }
            return sb.toString();
        }
    }

    @Override
    public String toString() {
        if (Verification.checkNull(this.messageExceptions)) {
            return super.toString();
        } else {
            StringBuilder sb = new StringBuilder(super.toString());
            sb.append("; message exceptions (").append(this.messageExceptions.length).append(") are:");
            for (int i = 0; i < this.messageExceptions.length; i++) {
                Exception subEx = this.messageExceptions[i];
                sb.append('\n').append("Failed message ").append(i + 1).append(": ");
                sb.append(subEx);
            }
            return sb.toString();
        }
    }

    @Override
    public void printStackTrace(PrintStream ps) {
        if (Verification.checkNull(this.messageExceptions)) {
            super.printStackTrace(ps);
        } else {
            ps.println(super.toString() + "; message exception details (" +
                    this.messageExceptions.length + ") are:");
            for (int i = 0; i < this.messageExceptions.length; i++) {
                Exception subEx = this.messageExceptions[i];
                ps.println("Failed message " + (i + 1) + ":");
                subEx.printStackTrace(ps);
            }
        }
    }

    @Override
    public void printStackTrace(PrintWriter pw) {
        if (Verification.checkNull(this.messageExceptions)) {
            super.printStackTrace(pw);
        } else {
            pw.println(super.toString() + "; message exception details (" +
                    this.messageExceptions.length + ") are:");
            for (int i = 0; i < this.messageExceptions.length; i++) {
                Exception subEx = this.messageExceptions[i];
                pw.println("Failed message " + (i + 1) + ":");
                subEx.printStackTrace(pw);
            }
        }
    }
}
